use thiserror::Error;

#[derive(Debug, Clone, Error)]
pub enum ConvertError {
    #[error("type mismatch, expected: {expected}, actual: {actual}")]
    TypeMismatch { expected: String, actual: String },

    #[error("element count mismatch, expected: {expected}, actual: {actual}")]
    CountMismatch { expected: usize, actual: usize },

    #[error("missing field: {0}")]
    MissingField(String),

    #[error("not exist variant: {0}")]
    NotExistVariant(String),
}

impl ConvertError {
    pub fn type_mismatch(expected: &str, actual: &str) -> Self {
        Self::TypeMismatch {
            expected: expected.into(),
            actual: actual.into(),
        }
    }

    pub fn count_mismatch(expected: usize, actual: usize) -> Self {
        Self::CountMismatch { expected, actual }
    }

    pub fn missing_field(field: &str) -> Self {
        Self::MissingField(field.into())
    }
}

#[derive(Debug, Error)]
pub enum InvokeError {
    #[error("function input arguments not matched")]
    ArgumentsNotMatched,

    #[error("function input convert error: {0}")]
    InputConvert(ConvertError),

    #[error("function output convert error: {0}")]
    OutputConvert(ConvertError),
}
